package com.graduation.project.service.system.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.graduation.project.entity.dto.menu.SaveOrUpdateMenuDTO;
import com.graduation.project.entity.dto.menu.ListMenuDTO;
import com.graduation.project.entity.dto.UpdateStatusDTO;
import com.graduation.project.entity.po.Menu;
import com.graduation.project.entity.po.RoleMenu;
import com.graduation.project.entity.vo.menu.ListMenuVO;
import com.graduation.project.entity.vo.menu.ListParentMenuVO;
import com.graduation.project.enums.ResultCodeEnum;
import com.graduation.project.mapper.system.MenuMapper;
import com.graduation.project.service.system.RoleMenuService;
import com.graduation.project.service.system.MenuManagementService;
import com.graduation.project.utils.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 卑微小峰
 * @date 2022/11/05
 * 菜单管理业务实现类
 */
@Service
public class MenuManagementServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuManagementService {

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private RoleMenuService roleMenuService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> addMenu(SaveOrUpdateMenuDTO input) {
        // 如果不是新增顶级，则查询新增菜单的父级菜单信息
        if (input.getParentMenuId() != 0) {
            LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Menu::getId, input.getParentMenuId());
            Menu menu = menuMapper.selectOne(queryWrapper);
            if (ObjectUtil.isNotEmpty(menu)) {
                // 按钮下不能新增
                if (menu.getMenuType() == 2) {
                    return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "按钮下不能新增");
                }
                // 目录下不能新增按钮
                if (menu.getMenuType() == 0 && input.getMenuType() == 2) {
                    return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "目录下不能新增按钮");
                }
                // 菜单下新增的不是按钮
                if (menu.getMenuType() == 1 && input.getMenuType() != 2) {
                    return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "菜单下只能新增按钮");
                }
            } else {
                return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "父级菜单不存在");
            }
        }

        Menu menu = new Menu();
        menu.setParentMenuId(input.getParentMenuId());
        menu.setMenuName(input.getMenuName());
        menu.setMenuType(input.getMenuType());
        menu.setMenuPerms(input.getMenuPerms());
        menu.setMenuSort(input.getMenuSort());
        // 新增目录
        if (input.getMenuType() == 0) {
            menu.setMenuIcon(input.getMenuIcon());
        }
        // 新增菜单
        if (input.getMenuType() == 1) {
            menu.setRoutePath(input.getRoutePath());
            menu.setRouteComponent(input.getRouteComponent());
            menu.setMenuIcon(input.getMenuIcon());
        }

        try {
            menuMapper.insert(menu);
        } catch (Exception e) {
            throw new RuntimeException("新增失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "新增成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> updateMenu(SaveOrUpdateMenuDTO input) {
        // 获取当前菜单详情
        LambdaQueryWrapper<Menu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Menu::getId, input.getId());
        Menu menu = menuMapper.selectOne(lambdaQueryWrapper);
        if (ObjectUtil.isNotEmpty(menu)) {
            // 不允许修改父级菜单
            if (menu.getId().equals(input.getParentMenuId())) {
                return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "父级菜单不能修改");
            }
            // 不允许修改菜单类型
            if (!menu.getMenuType().equals(input.getMenuType())) {
                return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "菜单类型不能修改");
            }
        } else {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "修改数据不存在");
        }
        BeanUtil.copyProperties(input, menu);
        try {
            menuMapper.updateById(menu);
        } catch (Exception e) {
            throw new RuntimeException();
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "修改成功");
    }

    @Override
    public ResultUtil<?> updateMenuStatusById(UpdateStatusDTO input) {
        // 判断当前数据是否存在
        Menu menu = menuMapper.selectOne(new LambdaQueryWrapper<Menu>()
                .eq(Menu::getId, input.getId()));
        if (ObjectUtil.isEmpty(menu)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "操作数据不存在");
        }
        List<Long> idList = new ArrayList<>();
        idList.add(input.getId());
        // 如果修改为启用状态：status=0，且当前不是顶级节点
        if (input.getStatus().equals(0) && menu.getParentMenuId() != 0) {
            // 判断其父节点是否为启用状态
            Menu res = menuMapper.selectOne(new LambdaQueryWrapper<Menu>()
                    .select(Menu::getMenuStatus)
                    .eq(Menu::getId, menu.getParentMenuId()));
            if (res.getMenuStatus().equals(1)) {
                return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "请先启用父级");
            }
        }
        // 如果修改为停用状态：status=1，且当前不是底级节点
        if (input.getStatus().equals(1) && menu.getMenuType() != 2) {
            // 查询全部菜单
            List<Menu> menus = menuMapper.selectList(new LambdaQueryWrapper<Menu>()
                    .select(
                            Menu::getId,
                            Menu::getParentMenuId,
                            Menu::getMenuType
                    ));
            // 过滤出当前节点的子树，并将id进行扁平化处理
            this.getChildMenuId(menus, input.getId(), idList);
        }
        // 修改状态
        for (Long a : idList) {
            menuMapper.update(null, new LambdaUpdateWrapper<Menu>()
                    .set(Menu::getMenuStatus, input.getStatus())
                    .eq(Menu::getId, a));
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "操作成功");
    }

    private List<Long> getChildMenuId(List<Menu> menus, Long id, List<Long> idList) {
        for (Menu menu : menus) {
            if (id.equals(menu.getParentMenuId())) {
                idList.add(menu.getId());
                if (menu.getMenuType() != 2) {
                    this.getChildMenuId(menus, menu.getId(), idList);
                }
            }
        }
        return idList;
    }

    @Override
    public ResultUtil<?> listMenuByCondition(ListMenuDTO input) {
        LambdaQueryWrapper<Menu> lambdaQueryMenuWrapper = new LambdaQueryWrapper<>();
        lambdaQueryMenuWrapper
                .like(StringUtils.isNotBlank(input.getMenuName()), Menu::getMenuName, input.getMenuName())
                .like(StringUtils.isNotBlank(input.getMenuPerms()), Menu::getMenuPerms, input.getMenuPerms())
                .eq(input.getMenuStatus() != null, Menu::getMenuStatus, input.getMenuStatus());

        List<Menu> allMenu = menuMapper.selectList(lambdaQueryMenuWrapper);

        List<ListMenuVO> listMenuVOList = allMenu.stream()
                .map(menu -> {
                    ListMenuVO menuVO = new ListMenuVO();
                    BeanUtil.copyProperties(menu, menuVO);
                    return menuVO;
                })
                .collect(Collectors.toList());

        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "查询成功", listMenuVOList);
    }

    @Override
    public ResultUtil<?> deleteMenu(Long id) {
        if (StringUtils.isBlank(id.toString())) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "参数不能为空");
        }
        // 查询全部菜单
        List<Menu> menus = menuMapper.selectList(new LambdaQueryWrapper<Menu>()
                .select(
                        Menu::getId,
                        Menu::getParentMenuId,
                        Menu::getMenuType
                ));

        List<Long> idList = new ArrayList<>();
        idList.add(id);
        // 过滤出当前节点的子树,并将id进行扁平化处理
        this.getChildMenuId(menus, id, idList);
        // 删除数据
        for (Long a : idList) {
            menuMapper.delete(new LambdaQueryWrapper<Menu>().eq(Menu::getId, a));
            // 删除角色菜单关系数据
            roleMenuService.remove(new LambdaQueryWrapper<RoleMenu>().eq(RoleMenu::getMenuId, id));
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "删除成功");
    }

    @Override
    public ResultUtil<?> listParentMenu() {
        // 查询下拉菜单类型不是按钮的所有数据
        List<Menu> menus = menuMapper.selectList(new LambdaQueryWrapper<Menu>()
                .select(
                        Menu::getId,
                        Menu::getMenuName,
                        Menu::getMenuType,
                        Menu::getParentMenuId
                )
                .ne(Menu::getMenuType, 2));
        List<ListParentMenuVO> listParentMenuVOList = menus.stream()
            .map(menu -> {
                ListParentMenuVO listParentMenuVO = new ListParentMenuVO();
                BeanUtil.copyProperties(menu, listParentMenuVO);
                return listParentMenuVO;
            })
            .collect(Collectors.toList());
        return ResultUtil.Success(ResultCodeEnum.SUCCESS, listParentMenuVOList);
    }
}
